package com.tongcao.cn.thread.pool;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author:tongcao
 * @since:2019/6/19 17:03
 * Description:默认线程池
 */
public class DefeaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {

    /**
     * 线程池维护工作者线程的最大数量
     */
    private static final int MAX_WORKER_NUMBERS = 30;

    /**
     * 线程池维护工作者线程的最默认工作数量
     */
    private static final int DEFAULT_WORKER_NUMBERS = 5;

    /**
     * 线程池维护工作者线程的最小数量
     */
    private static final int MIN_WORKER_NUMBERS = 1;


    /**
     * 维护一个工作列表,里面加入客户端发起的工作(先进先出)
     */
    private final LinkedList<Job> jobs = new LinkedList<Job>();

    /**
     * 工作者线程的列表
     */
    private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());


    /**
     * 工作者线程的数量
     */
    private int workerNum;

    /**
     * 每个工作者线程编号生成 (进行原子操作)
     */
    private AtomicLong threadNum = new AtomicLong();


    /**
     * 第一步:构造函数，用于初始化线程池
     * 首先判断初始化线程池的线程个数是否大于最大线程数，如果大于则线程池的默认初始化值为 DEFAULT_WORKER_NUMBERS
     */
    public DefeaultThreadPool(int num) {
        if (num > MAX_WORKER_NUMBERS) {
            this.workerNum = DEFAULT_WORKER_NUMBERS;

        } else {
            this.workerNum = num;
        }
        initWorkers(num);
    }

    /**
     * 初始化每个工作者线程
     *
     * @param num
     */
    private void initWorkers(int num) {
        for (int i = 0; i < num; i++) {
            Worker worker = new Worker();
            workers.add(worker);

            Thread thread = new Thread(worker);
            thread.start();
        }
    }

    @Override
    public void execute(Job job) {
        //如果job为null，抛出空指针
        if (job == null) {
            throw new NullPointerException();
        }

        //这里进行执行 TODO 当供大于求时候，考虑如何临时添加线程数
        if (job != null) {
            synchronized (jobs) {
                jobs.addLast(job);
                jobs.notify();
            }

        }
    }

    @Override
    public void shutdown() {
        for (Worker worker : workers) {
            worker.shutdown();
        }
    }

    @Override
    public void addWorker(int num) {
        synchronized (jobs) {
            if (num + workerNum > MAX_WORKER_NUMBERS) {
                num = MAX_WORKER_NUMBERS - workerNum;
            }
            //todo init workers
            initWorkers(num);
            this.workerNum += num;
        }
    }

    /**
     * 减少工作者线程
     *
     * @param num
     */
    @Override
    public void removeWorker(int num) {
        synchronized (jobs) {
            if (num > workerNum) {
                throw new IllegalArgumentException("超过了已有的线程数量");
            }

            for (int i = 0; i < num; i++) {
                Worker worker = workers.get(i);
                worker.shutdown();
                workers.remove(i);
            }

            this.workerNum -= num;
        }
    }

    @Override
    public int getJobSize() {
        return jobs.size();
    }

    class Worker implements Runnable {
        // 表示是否运行该worker
        private volatile boolean running = true;

        @Override
        public void run() {
            while (running) {
                Job job = null;
                synchronized (jobs) {
                    if (jobs.isEmpty()) {
                        try {
                            jobs.wait();//线程等待唤醒
                        } catch (InterruptedException e) {
                            //感知到外部对该线程的中断操作，返回
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    job = jobs.removeFirst();
                    //执行job
                    if (job != null) {
                        job.run();
                    }
                }
            }
        }

        /**
         * 终止该线程
         */
        public void shutdown() {
            this.running = false;
        }
    }


}